using CollabApp.Domain.Services.Game;
using CollabApp.Application.Interfaces;
using Microsoft.Extensions.Logging;
using System.Text.Json;

namespace CollabApp.Application.Services.Game;

/// <summary>
/// 动态平衡服务实现
/// 负责实现游戏的动态平衡机制，确保游戏的公平性和趣味性
/// </summary>
public class DynamicBalanceService : IDynamicBalanceService
{
    private readonly IRedisService _redisService;
    private readonly IPlayerStateService _playerStateService;
    private readonly ITerritoryService _territoryService;
    private readonly ILogger<DynamicBalanceService> _logger;

    /// <summary>
    /// 平衡机制常量
    /// </summary>
    private static class BalanceConstants
    {
        public const float DominantPlayerThreshold = 40.0f; // 40%面积触发橡皮筋机制
        public const float LeaderSpeedDebuff = 0.95f; // 领先玩家速度-5%
        public const float LaggingSpeedBuff = 1.2f; // 落后玩家速度+20%
        public const float LaggingPowerUpBuff = 1.2f; // 落后玩家道具效果+20%
        public const int BalanceEffectDuration = 30; // 平衡效果持续30秒
        public const int RubberBandDuration = 60; // 橡皮筋联盟持续60秒
    }

    /// <summary>
    /// Redis键模板
    /// </summary>
    private static class RedisKeys
    {
        public const string PlayerBalanceStatus = "game:{0}:balance:player:{1}";
        public const string GameBalanceState = "game:{0}:balance:state";
        public const string RubberBandAlliance = "game:{0}:rubber_band";
    }

    public DynamicBalanceService(
        IRedisService redisService,
        IPlayerStateService playerStateService,
        ITerritoryService territoryService,
        ILogger<DynamicBalanceService> logger)
    {
        _redisService = redisService;
        _playerStateService = playerStateService;
        _territoryService = territoryService;
        _logger = logger;
    }

    /// <summary>
    /// 计算玩家的动态平衡修正值
    /// </summary>
    public async Task<BalanceModifierResult> CalculateBalanceModifiersAsync(Guid gameId, Guid playerId)
    {
        try
        {
            // 获取玩家当前状态和排名
            var playerState = await _playerStateService.GetPlayerStateAsync(gameId, playerId);
            if (playerState == null)
            {
                return new BalanceModifierResult
                {
                    Success = false,
                    Errors = { "无法获取玩家状态" }
                };
            }

            var rankings = await _playerStateService.GetGameRankingAsync(gameId);
            var playerRanking = rankings.FirstOrDefault(r => r.PlayerId == playerId);
            if (playerRanking == null)
            {
                return new BalanceModifierResult
                {
                    Success = false,
                    Errors = { "无法获取玩家排名信息" }
                };
            }

            var totalPlayers = rankings.Count;
            var playerRank = playerRanking.Rank;
            var territoryPercentage = playerRanking.AreaPercentage;

            var result = new BalanceModifierResult
            {
                Success = true,
                PlayerId = playerId,
                PlayerRank = playerRank,
                TerritoryPercentage = territoryPercentage
            };

            // 检查是否为主导玩家（触发橡皮筋机制）
            if (territoryPercentage >= BalanceConstants.DominantPlayerThreshold)
            {
                result.EffectType = BalanceEffectType.None; // 橡皮筋机制会单独处理
                result.EffectDescription = $"主导玩家（{territoryPercentage:F1}%领地），橡皮筋机制激活";
                result.Messages.Add("您的领地面积过大，其他玩家将获得联盟buff");
                
                return result;
            }

            // 领先玩家debuff（排名前25%且不是主导玩家）
            if (playerRank <= Math.Max(1, totalPlayers / 4))
            {
                result.SpeedModifier = BalanceConstants.LeaderSpeedDebuff;
                result.IsLeadingPlayer = true;
                result.EffectType = BalanceEffectType.LeaderSpeedDebuff;
                result.EffectDescription = $"领先玩家减速（排名第{playerRank}）";
                result.EffectDurationSeconds = BalanceConstants.BalanceEffectDuration;
                result.Messages.Add($"作为领先玩家，您的移动速度降低{(1 - BalanceConstants.LeaderSpeedDebuff) * 100:F0}%");
            }
            // 落后玩家buff（排名后50%）
            else if (playerRank > totalPlayers / 2)
            {
                result.SpeedModifier = BalanceConstants.LaggingSpeedBuff;
                result.PowerUpEffectMultiplier = BalanceConstants.LaggingPowerUpBuff;
                result.IsLaggingPlayer = true;
                result.EffectType = BalanceEffectType.LagginPlayerSpeedBuff;
                result.EffectDescription = $"落后玩家buff（排名第{playerRank}）";
                result.EffectDurationSeconds = BalanceConstants.BalanceEffectDuration;
                result.Messages.Add($"落后玩家buff：移动速度+{(BalanceConstants.LaggingSpeedBuff - 1) * 100:F0}%，道具效果+{(BalanceConstants.LaggingPowerUpBuff - 1) * 100:F0}%");
            }
            else
            {
                // 中等排名，无特殊效果
                result.EffectType = BalanceEffectType.None;
                result.EffectDescription = "平衡状态，无特殊效果";
            }

            _logger.LogDebug("计算动态平衡修正 - GameId: {GameId}, PlayerId: {PlayerId}, Rank: {Rank}/{Total}, Effect: {Effect}", 
                gameId, playerId, playerRank, totalPlayers, result.EffectType);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "计算动态平衡修正失败 - GameId: {GameId}, PlayerId: {PlayerId}", gameId, playerId);
            return new BalanceModifierResult
            {
                Success = false,
                Errors = { "计算平衡修正时发生内部错误" }
            };
        }
    }

    /// <summary>
    /// 检查是否需要启用橡皮筋机制
    /// </summary>
    public async Task<RubberBandResult> CheckRubberBandMechanismAsync(Guid gameId)
    {
        try
        {
            var rankings = await _playerStateService.GetGameRankingAsync(gameId);
            var result = new RubberBandResult();
            
            // 查找主导玩家（领地面积超过40%）
            var dominantPlayer = rankings.FirstOrDefault(r => 
                r.AreaPercentage >= BalanceConstants.DominantPlayerThreshold);

            if (dominantPlayer == null)
            {
                result.ShouldActivate = false;
                result.Messages.Add("无主导玩家，橡皮筋机制未激活");
                return result;
            }

            // 检查是否已经激活橡皮筋机制
            var rubberBandKey = string.Format(RedisKeys.RubberBandAlliance, gameId);
            var existingAlliance = await _redisService.GetStringAsync(rubberBandKey);
            
            if (!string.IsNullOrEmpty(existingAlliance))
            {
                try
                {
                    var allianceData = JsonSerializer.Deserialize<RubberBandResult>(existingAlliance);
                    if (allianceData != null)
                    {
                        // 检查联盟是否仍然有效
                        var allianceAge = DateTime.UtcNow - DateTime.Parse(allianceData.Messages.LastOrDefault() ?? DateTime.UtcNow.ToString());
                        if (allianceAge.TotalSeconds < BalanceConstants.RubberBandDuration)
                        {
                            return allianceData; // 返回现有联盟
                        }
                    }
                }
                catch (JsonException)
                {
                    // 数据格式错误，重新创建
                }
            }

            // 激活橡皮筋机制
            result.ShouldActivate = true;
            result.DominantPlayerId = dominantPlayer.PlayerId;
            result.DominantPlayerName = dominantPlayer.PlayerName;
            result.DominantPlayerAreaPercentage = dominantPlayer.AreaPercentage;
            
            // 获取联盟成员（除主导玩家外的其他玩家）
            result.AlliancePlayerIds = rankings
                .Where(r => r.PlayerId != dominantPlayer.PlayerId)
                .Select(r => r.PlayerId)
                .ToList();

            result.AllianceBuffDescription = "联盟成员间轨迹不致命，可以穿越";
            result.AllianceDurationSeconds = BalanceConstants.RubberBandDuration;
            result.Messages.Add($"主导玩家 {dominantPlayer.PlayerName} 占据 {dominantPlayer.AreaPercentage:F1}% 领地");
            result.Messages.Add($"橡皮筋联盟激活，{result.AlliancePlayerIds.Count} 名玩家获得联盟buff");
            result.Messages.Add(DateTime.UtcNow.ToString()); // 用于计算联盟持续时间

            // 保存联盟状态
            var allianceJson = JsonSerializer.Serialize(result);
            await _redisService.SetStringAsync(rubberBandKey, allianceJson, TimeSpan.FromSeconds(BalanceConstants.RubberBandDuration));

            _logger.LogInformation("橡皮筋机制激活 - GameId: {GameId}, DominantPlayer: {PlayerId} ({Area:F1}%), Alliance: {AllianceCount} players", 
                gameId, dominantPlayer.PlayerId, dominantPlayer.AreaPercentage, result.AlliancePlayerIds.Count);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "检查橡皮筋机制失败 - GameId: {GameId}", gameId);
            return new RubberBandResult
            {
                ShouldActivate = false,
                Messages = { "检查橡皮筋机制时发生错误" }
            };
        }
    }

    /// <summary>
    /// 应用动态平衡效果
    /// </summary>
    public async Task<bool> ApplyBalanceModifiersAsync(Guid gameId, Guid playerId, BalanceModifierResult modifiers)
    {
        try
        {
            if (!modifiers.Success || modifiers.EffectType == BalanceEffectType.None)
            {
                return true; // 无需应用效果
            }

            var balanceStatus = new PlayerBalanceStatus
            {
                PlayerId = playerId,
                CurrentRank = modifiers.PlayerRank,
                TerritoryPercentage = modifiers.TerritoryPercentage,
                BalanceType = DetermineBalanceType(modifiers),
                LastUpdateTime = DateTime.UtcNow
            };

            // 创建活跃效果
            var activeEffect = new ActiveBalanceEffect
            {
                EffectId = $"balance_{gameId}_{playerId}_{DateTime.UtcNow.Ticks}",
                EffectType = modifiers.EffectType,
                EffectValue = GetEffectValue(modifiers),
                StartTime = DateTime.UtcNow,
                RemainingSeconds = modifiers.EffectDurationSeconds,
                Description = modifiers.EffectDescription,
                IsActive = true
            };

            balanceStatus.ActiveEffects.Add(activeEffect);

            // 保存到Redis
            var statusKey = string.Format(RedisKeys.PlayerBalanceStatus, gameId, playerId);
            var statusJson = JsonSerializer.Serialize(balanceStatus);
            await _redisService.SetStringAsync(statusKey, statusJson, TimeSpan.FromSeconds(modifiers.EffectDurationSeconds + 10));

            _logger.LogDebug("应用动态平衡效果 - GameId: {GameId}, PlayerId: {PlayerId}, Effect: {Effect}, Value: {Value}", 
                gameId, playerId, modifiers.EffectType, GetEffectValue(modifiers));

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "应用动态平衡效果失败 - GameId: {GameId}, PlayerId: {PlayerId}", gameId, playerId);
            return false;
        }
    }

    /// <summary>
    /// 获取所有玩家的平衡状态
    /// </summary>
    public async Task<List<PlayerBalanceStatus>> GetAllPlayersBalanceStatusAsync(Guid gameId)
    {
        try
        {
            var rankings = await _playerStateService.GetGameRankingAsync(gameId);
            var balanceStatuses = new List<PlayerBalanceStatus>();

            foreach (var ranking in rankings)
            {
                var statusKey = string.Format(RedisKeys.PlayerBalanceStatus, gameId, ranking.PlayerId);
                var statusJson = await _redisService.GetStringAsync(statusKey);

                if (!string.IsNullOrEmpty(statusJson))
                {
                    try
                    {
                        var status = JsonSerializer.Deserialize<PlayerBalanceStatus>(statusJson);
                        if (status != null)
                        {
                            // 更新实时数据
                            status.CurrentRank = ranking.Rank;
                            status.TerritoryPercentage = ranking.AreaPercentage;
                            status.PlayerName = ranking.PlayerName;

                            // 更新活跃效果的剩余时间
                            var currentTime = DateTime.UtcNow;
                            foreach (var effect in status.ActiveEffects)
                            {
                                var elapsed = currentTime - effect.StartTime;
                                effect.RemainingSeconds = Math.Max(0, effect.RemainingSeconds - (int)elapsed.TotalSeconds);
                                effect.IsActive = effect.RemainingSeconds > 0;
                            }

                            // 移除过期效果
                            status.ActiveEffects = status.ActiveEffects.Where(e => e.IsActive).ToList();

                            balanceStatuses.Add(status);
                        }
                    }
                    catch (JsonException ex)
                    {
                        _logger.LogWarning(ex, "解析玩家平衡状态失败 - GameId: {GameId}, PlayerId: {PlayerId}", 
                            gameId, ranking.PlayerId);
                    }
                }
                else
                {
                    // 创建默认状态
                    balanceStatuses.Add(new PlayerBalanceStatus
                    {
                        PlayerId = ranking.PlayerId,
                        PlayerName = ranking.PlayerName,
                        CurrentRank = ranking.Rank,
                        TerritoryPercentage = ranking.AreaPercentage,
                        BalanceType = PlayerBalanceType.Balanced,
                        LastUpdateTime = DateTime.UtcNow
                    });
                }
            }

            return balanceStatuses;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取所有玩家平衡状态失败 - GameId: {GameId}", gameId);
            return new List<PlayerBalanceStatus>();
        }
    }

    /// <summary>
    /// 更新游戏平衡状态
    /// </summary>
    public async Task<BalanceUpdateResult> UpdateGameBalanceAsync(Guid gameId)
    {
        try
        {
            var result = new BalanceUpdateResult { Success = true };
            var rankings = await _playerStateService.GetGameRankingAsync(gameId);
            
            if (!rankings.Any())
            {
                return result;
            }

            // 检查橡皮筋机制
            var rubberBandResult = await CheckRubberBandMechanismAsync(gameId);
            result.RubberBandActivated = rubberBandResult.ShouldActivate;
            result.RubberBandDominantPlayer = rubberBandResult.DominantPlayerId;

            // 为每个玩家计算和应用平衡修正
            foreach (var ranking in rankings)
            {
                var modifiers = await CalculateBalanceModifiersAsync(gameId, ranking.PlayerId);
                if (modifiers.Success)
                {
                    var applied = await ApplyBalanceModifiersAsync(gameId, ranking.PlayerId, modifiers);
                    if (applied)
                    {
                        result.UpdatedPlayersCount++;
                        if (modifiers.EffectType != BalanceEffectType.None)
                        {
                            result.NewEffectsCount++;
                            result.UpdateDetails.Add($"{ranking.PlayerName}: {modifiers.EffectDescription}");
                        }
                    }
                }
            }

            // 处理橡皮筋联盟
            if (rubberBandResult.ShouldActivate)
            {
                foreach (var alliancePlayerId in rubberBandResult.AlliancePlayerIds)
                {
                    await ApplyRubberBandAllianceBuffAsync(gameId, alliancePlayerId, rubberBandResult);
                }
                
                result.UpdateDetails.Add($"橡皮筋联盟激活: {rubberBandResult.AlliancePlayerIds.Count} 名联盟成员");
            }

            _logger.LogInformation("游戏平衡状态更新完成 - GameId: {GameId}, Players: {Players}, RubberBand: {RubberBand}", 
                gameId, result.UpdatedPlayersCount, result.RubberBandActivated);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新游戏平衡状态失败 - GameId: {GameId}", gameId);
            return new BalanceUpdateResult
            {
                Success = false,
                Errors = { "更新平衡状态时发生内部错误" }
            };
        }
    }

    /// <summary>
    /// 清除所有平衡效果
    /// </summary>
    public async Task<bool> ClearAllBalanceEffectsAsync(Guid gameId)
    {
        try
        {
            var rankings = await _playerStateService.GetGameRankingAsync(gameId);
            var tasks = new List<Task<bool>>();

            foreach (var ranking in rankings)
            {
                var statusKey = string.Format(RedisKeys.PlayerBalanceStatus, gameId, ranking.PlayerId);
                tasks.Add(_redisService.KeyDeleteAsync(statusKey));
            }

            // 清除橡皮筋联盟状态
            var rubberBandKey = string.Format(RedisKeys.RubberBandAlliance, gameId);
            tasks.Add(_redisService.KeyDeleteAsync(rubberBandKey));

            // 清除游戏平衡状态
            var gameStateKey = string.Format(RedisKeys.GameBalanceState, gameId);
            tasks.Add(_redisService.KeyDeleteAsync(gameStateKey));

            await Task.WhenAll(tasks);

            _logger.LogInformation("清除所有平衡效果 - GameId: {GameId}", gameId);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "清除平衡效果失败 - GameId: {GameId}", gameId);
            return false;
        }
    }

    /// <summary>
    /// 应用橡皮筋联盟buff
    /// </summary>
    private async Task<bool> ApplyRubberBandAllianceBuffAsync(Guid gameId, Guid playerId, RubberBandResult rubberBandResult)
    {
        try
        {
            var statusKey = string.Format(RedisKeys.PlayerBalanceStatus, gameId, playerId);
            var statusJson = await _redisService.GetStringAsync(statusKey);
            
            PlayerBalanceStatus status;
            if (!string.IsNullOrEmpty(statusJson))
            {
                status = JsonSerializer.Deserialize<PlayerBalanceStatus>(statusJson) ?? new PlayerBalanceStatus();
            }
            else
            {
                status = new PlayerBalanceStatus
                {
                    PlayerId = playerId,
                    LastUpdateTime = DateTime.UtcNow
                };
            }

            // 添加橡皮筋联盟效果
            var allianceEffect = new ActiveBalanceEffect
            {
                EffectId = $"rubber_band_{gameId}_{playerId}_{DateTime.UtcNow.Ticks}",
                EffectType = BalanceEffectType.RubberBandTrailImmunity,
                EffectValue = 1.0f,
                StartTime = DateTime.UtcNow,
                RemainingSeconds = rubberBandResult.AllianceDurationSeconds,
                Description = rubberBandResult.AllianceBuffDescription,
                IsActive = true
            };

            status.ActiveEffects.Add(allianceEffect);
            status.InRubberBandAlliance = true;
            status.BalanceType = PlayerBalanceType.AllianceMember;
            status.LastUpdateTime = DateTime.UtcNow;

            // 保存更新状态
            var updatedJson = JsonSerializer.Serialize(status);
            await _redisService.SetStringAsync(statusKey, updatedJson, TimeSpan.FromSeconds(rubberBandResult.AllianceDurationSeconds + 10));

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "应用橡皮筋联盟buff失败 - GameId: {GameId}, PlayerId: {PlayerId}", gameId, playerId);
            return false;
        }
    }

    /// <summary>
    /// 确定玩家平衡类型
    /// </summary>
    private static PlayerBalanceType DetermineBalanceType(BalanceModifierResult modifiers)
    {
        if (modifiers.TerritoryPercentage >= BalanceConstants.DominantPlayerThreshold)
            return PlayerBalanceType.Dominant;
        
        if (modifiers.IsLeadingPlayer)
            return PlayerBalanceType.Leading;
        
        if (modifiers.IsLaggingPlayer)
            return PlayerBalanceType.Lagging;
        
        return PlayerBalanceType.Balanced;
    }

    /// <summary>
    /// 获取效果数值
    /// </summary>
    private static float GetEffectValue(BalanceModifierResult modifiers)
    {
        return modifiers.EffectType switch
        {
            BalanceEffectType.LeaderSpeedDebuff => modifiers.SpeedModifier,
            BalanceEffectType.LagginPlayerSpeedBuff => modifiers.SpeedModifier,
            BalanceEffectType.LaggingPlayerPowerUpBuff => modifiers.PowerUpEffectMultiplier,
            _ => 1.0f
        };
    }
}
